﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace PlaygroundSplines
{
	// Token: 0x02000149 RID: 329
	[ExecuteInEditMode]
	public class PlaygroundSpline : MonoBehaviour
	{
		// Token: 0x060006F6 RID: 1782 RVA: 0x0002948C File Offset: 0x0002768C
		public virtual bool IsReady()
		{
			return this.isReady;
		}

		// Token: 0x060006F7 RID: 1783 RVA: 0x00029494 File Offset: 0x00027694
		public virtual bool AddUser(Transform thisTransform)
		{
			if (!this.usedBy.Contains(thisTransform))
			{
				this.usedBy.Add(thisTransform);
				return true;
			}
			return false;
		}

		// Token: 0x060006F8 RID: 1784 RVA: 0x000294B8 File Offset: 0x000276B8
		public virtual bool RemoveUser(Transform thisTransform)
		{
			if (this.usedBy.Contains(thisTransform))
			{
				this.usedBy.Remove(thisTransform);
				return true;
			}
			return false;
		}

		// Token: 0x060006F9 RID: 1785 RVA: 0x000294DC File Offset: 0x000276DC
		public virtual bool HasUser(Transform thisTransform)
		{
			return this.usedBy.Contains(thisTransform);
		}

		// Token: 0x170000C9 RID: 201
		// (get) Token: 0x060006FA RID: 1786 RVA: 0x000294EC File Offset: 0x000276EC
		// (set) Token: 0x060006FB RID: 1787 RVA: 0x000294F4 File Offset: 0x000276F4
		public bool Loop
		{
			get
			{
				return this.loop;
			}
			set
			{
				this.loop = value;
				if (value && this.NodeCount > 1)
				{
					this.modes[this.modes.Count - 1] = this.modes[0];
					this.SetControlPoint(0, this.points[0]);
				}
			}
		}

		// Token: 0x170000CA RID: 202
		// (get) Token: 0x060006FC RID: 1788 RVA: 0x00029554 File Offset: 0x00027754
		public int ControlPointCount
		{
			get
			{
				return this.points.Count;
			}
		}

		// Token: 0x060006FD RID: 1789 RVA: 0x00029564 File Offset: 0x00027764
		public virtual Vector3 GetControlPoint(int index)
		{
			return this.GetPoint(index);
		}

		// Token: 0x060006FE RID: 1790 RVA: 0x00029570 File Offset: 0x00027770
		public virtual void SetControlPoint(int index, Vector3 point, Vector3 offset)
		{
			this.SetControlPoint(index, point - offset);
		}

		// Token: 0x060006FF RID: 1791 RVA: 0x00029580 File Offset: 0x00027780
		public virtual void SetControlPoint(int index, Vector3 point)
		{
			if (index < 0)
			{
				index = 0;
			}
			if (index % 3 == 0)
			{
				Vector3 b = point - this.GetPoint(index);
				if (this.loop)
				{
					if (index == 0)
					{
						Vector3 point2 = this.GetPoint(1);
						this.SetPoint(1, point2 + b);
						point2 = this.GetPoint(this.points.Count - 2);
						this.SetPoint(this.points.Count - 2, point2 + b);
						if (this.moveTransformsAsBeziers || !this.PointHasTransform(this.points.Count - 1))
						{
							this.SetPoint(this.points.Count - 1, point);
						}
					}
					else if (index == this.points.Count - 1)
					{
						this.SetPoint(0, point);
						Vector3 point2 = this.GetPoint(1);
						this.SetPoint(1, point2 + b);
						point2 = this.GetPoint(index - 1);
						this.SetPoint(index - 1, point2 + b);
					}
					else
					{
						Vector3 point2 = this.GetPoint(index - 1);
						this.SetPoint(index - 1, point2 + b);
						point2 = this.GetPoint(index + 1);
						this.SetPoint(index + 1, point2 + b);
					}
				}
				else
				{
					if (index > 0 && (this.moveTransformsAsBeziers || !this.PointHasTransform(index - 1)))
					{
						Vector3 point2 = this.GetPoint(index - 1);
						this.SetPoint(index - 1, point2 + b);
					}
					if (index + 1 < this.points.Count && (this.moveTransformsAsBeziers || !this.PointHasTransform(index + 1)))
					{
						Vector3 point2 = this.GetPoint(index + 1);
						this.SetPoint(index + 1, point2 + b);
					}
				}
			}
			this.SetPoint(index, point);
			this.EnforceMode(index);
		}

		// Token: 0x06000700 RID: 1792 RVA: 0x00029758 File Offset: 0x00027958
		public virtual void SetPoints(Vector3[] vectors)
		{
			if (vectors.Length != this.points.Count)
			{
				global::Debug.Log(string.Concat(new object[]
				{
					"Please ensure the same length of your passed in vectors (",
					vectors.Length,
					") as the current points (",
					this.points.Count,
					"). Use PlaygroundSpline.ControlPointCount to get the current count."
				}));
				return;
			}
			for (int i = 0; i < this.points.Count; i++)
			{
				this.points[i] = vectors[i];
			}
		}

		// Token: 0x06000701 RID: 1793 RVA: 0x000297F4 File Offset: 0x000279F4
		public virtual bool PointHasTransform(int index)
		{
			return this.transformNodes[index].IsAvailable();
		}

		// Token: 0x06000702 RID: 1794 RVA: 0x00029808 File Offset: 0x00027A08
		public virtual void TranslateSpline(Vector3 translation)
		{
			for (int i = 0; i < this.points.Count; i++)
			{
				List<Vector3> list2;
				List<Vector3> list = list2 = this.points;
				int index2;
				int index = index2 = i;
				Vector3 a = list2[index2];
				list[index] = a + translation;
			}
		}

		// Token: 0x06000703 RID: 1795 RVA: 0x00029850 File Offset: 0x00027A50
		public virtual Vector3 GetTransformPosition()
		{
			return this.previousPosition;
		}

		// Token: 0x06000704 RID: 1796 RVA: 0x00029858 File Offset: 0x00027A58
		public virtual Quaternion GetTransformRotation()
		{
			return this.previousRotation;
		}

		// Token: 0x06000705 RID: 1797 RVA: 0x00029860 File Offset: 0x00027A60
		public virtual Vector3 GetTransformScale()
		{
			return this.previousScale;
		}

		// Token: 0x06000706 RID: 1798 RVA: 0x00029868 File Offset: 0x00027A68
		public virtual BezierControlPointMode GetControlPointMode(int index)
		{
			return this.modes[(index + 1) / 3];
		}

		// Token: 0x06000707 RID: 1799 RVA: 0x0002987C File Offset: 0x00027A7C
		public virtual void SetControlPointMode(int index, BezierControlPointMode mode)
		{
			int num = (index + 1) / 3;
			this.modes[num] = mode;
			if (this.loop)
			{
				if (num == 0)
				{
					this.modes[this.modes.Count - 1] = mode;
				}
				else if (num == this.modes.Count - 1)
				{
					this.modes[0] = mode;
				}
			}
			this.EnforceMode(index);
		}

		// Token: 0x06000708 RID: 1800 RVA: 0x000298F4 File Offset: 0x00027AF4
		public virtual void EnforceMode(int index)
		{
			int num = (index + 1) / 3;
			BezierControlPointMode bezierControlPointMode = this.modes[num];
			if (bezierControlPointMode == BezierControlPointMode.Free || (!this.loop && (num == 0 || num == this.modes.Count - 1)))
			{
				return;
			}
			int num2 = num * 3;
			int num3;
			int num4;
			if (index <= num2)
			{
				num3 = num2 - 1;
				if (num3 < 0)
				{
					num3 = this.points.Count - 2;
				}
				num4 = num2 + 1;
				if (num4 >= this.points.Count)
				{
					num4 = 1;
				}
			}
			else
			{
				num3 = num2 + 1;
				if (num3 >= this.points.Count)
				{
					num3 = 1;
				}
				num4 = num2 - 1;
				if (num4 < 0)
				{
					num4 = this.points.Count - 2;
				}
			}
			Vector3 point = this.GetPoint(num2);
			Vector3 b = point - this.GetPoint(num3);
			if (bezierControlPointMode == BezierControlPointMode.Aligned)
			{
				b = b.normalized * Vector3.Distance(point, this.GetPoint(num4));
			}
			if (this.moveTransformsAsBeziers || !this.PointHasTransform(num4))
			{
				this.SetPoint(num4, point + b);
			}
		}

		// Token: 0x170000CB RID: 203
		// (get) Token: 0x06000709 RID: 1801 RVA: 0x00029A1C File Offset: 0x00027C1C
		public int NodeCount
		{
			get
			{
				return (this.points.Count - 1) / 3;
			}
		}

		// Token: 0x0600070A RID: 1802 RVA: 0x00029A30 File Offset: 0x00027C30
		public virtual Vector3 GetPoint(float t)
		{
			if (this.reverse)
			{
				t = 1f - t;
				t = (t - this.timeOffset) % 1f;
				if (t < 0f)
				{
					t = 1f + t;
				}
			}
			else
			{
				t = (t + this.timeOffset) % 1f;
			}
			int num;
			if (t >= 1f)
			{
				num = this.points.Count - 4;
			}
			else
			{
				t = Mathf.Clamp01(t) * (float)this.NodeCount;
				num = (int)t;
				t -= (float)num;
				num *= 3;
			}
			return this.splineTransformMx.MultiplyPoint3x4(PlaygroundSplines.Bezier.GetPoint(this.GetInversePoint(num), this.GetInversePoint(num + 1), this.GetInversePoint(num + 2), this.GetInversePoint(num + 3), t) + this.positionOffset);
		}

		// Token: 0x0600070B RID: 1803 RVA: 0x00029B04 File Offset: 0x00027D04
		public virtual Vector3 GetVelocity(float t)
		{
			if (this.reverse)
			{
				t = 1f - t;
			}
			t = (t + this.timeOffset) % 1f;
			int num;
			if (t >= 1f)
			{
				t = 1f;
				num = this.points.Count - 4;
			}
			else
			{
				t = Mathf.Clamp01(t) * (float)this.NodeCount;
				num = (int)t;
				t -= (float)num;
				num *= 3;
			}
			return this.splineTransformMx.MultiplyPoint3x4(PlaygroundSplines.Bezier.GetFirstDerivative(this.GetInversePoint(num), this.GetInversePoint(num + 1), this.GetInversePoint(num + 2), this.GetInversePoint(num + 3), t) + this.positionOffset) - this.previousPosition;
		}

		// Token: 0x0600070C RID: 1804 RVA: 0x00029BC0 File Offset: 0x00027DC0
		public virtual Vector3 GetPoint(int index)
		{
			if (this.transformNodes[index].IsAvailable())
			{
				return this.transformNodes[index].GetPosition();
			}
			return this.points[index];
		}

		// Token: 0x0600070D RID: 1805 RVA: 0x00029BF8 File Offset: 0x00027DF8
		public virtual Vector3 GetInversePoint(int index)
		{
			if (this.transformNodes[index].IsAvailable())
			{
				return this.transformNodes[index].GetInvsersePosition();
			}
			return this.points[index];
		}

		// Token: 0x0600070E RID: 1806 RVA: 0x00029C30 File Offset: 0x00027E30
		public virtual Vector3 GetPointWorldSpace(int index)
		{
			if (this.transformNodes[index].IsAvailable())
			{
				return this.transformNodes[index].GetPosition();
			}
			return this.splineTransformMx.MultiplyPoint3x4(this.points[index] + this.positionOffset);
		}

		// Token: 0x0600070F RID: 1807 RVA: 0x00029C88 File Offset: 0x00027E88
		public virtual void SetPoint(int index, Vector3 position)
		{
			if (this.transformNodes[index].IsAvailable())
			{
				this.transformNodes[index].SetPosition(position);
			}
			else
			{
				this.points[index] = position;
			}
		}

		// Token: 0x06000710 RID: 1808 RVA: 0x00029CC4 File Offset: 0x00027EC4
		public virtual void TranslatePoint(int index, Vector3 translation)
		{
			if (this.transformNodes[index].IsAvailable())
			{
				this.transformNodes[index].Translate(translation);
			}
			else
			{
				List<Vector3> list2;
				List<Vector3> list = list2 = this.points;
				Vector3 a = list2[index];
				list[index] = a + translation;
			}
		}

		// Token: 0x06000711 RID: 1809 RVA: 0x00029D20 File Offset: 0x00027F20
		public virtual float CPOB(Vector3 aP, float aStart, float aEnd, int aSteps)
		{
			aStart = Mathf.Clamp01(aStart);
			aEnd = Mathf.Clamp01(aEnd);
			float num = (aEnd - aStart) / (float)aSteps;
			float result = 0f;
			float num2 = float.MaxValue;
			for (int i = 0; i < aSteps; i++)
			{
				float num3 = aStart + num * (float)i;
				float sqrMagnitude = (this.GetPoint(num3) - aP).sqrMagnitude;
				if (sqrMagnitude < num2)
				{
					num2 = sqrMagnitude;
					result = num3;
				}
			}
			return result;
		}

		// Token: 0x06000712 RID: 1810 RVA: 0x00029D94 File Offset: 0x00027F94
		public virtual float ClosestTimeFromPoint(Vector3 aP)
		{
			float num = this.CPOB(aP, 0f, 1f, 10);
			float num2 = 0.1f;
			for (int i = 0; i < 4; i++)
			{
				num = this.CPOB(aP, num - num2, num + num2, 10);
				num2 /= 9f;
			}
			return num;
		}

		// Token: 0x06000713 RID: 1811 RVA: 0x00029DE8 File Offset: 0x00027FE8
		public virtual Vector3 ClosestPointFromPosition(Vector3 aP)
		{
			return this.GetPoint(this.ClosestTimeFromPoint(aP));
		}

		// Token: 0x06000714 RID: 1812 RVA: 0x00029DF8 File Offset: 0x00027FF8
		public virtual Vector3 GetDirection(float t)
		{
			return (this.GetPoint(t + 0.001f) - this.GetPoint(t)).normalized;
		}

		// Token: 0x06000715 RID: 1813 RVA: 0x00029E28 File Offset: 0x00028028
		public virtual void AddNode()
		{
			this.AddNode((this.points.Count - 1) / 3);
		}

		// Token: 0x06000716 RID: 1814 RVA: 0x00029E40 File Offset: 0x00028040
		public virtual void AddNode(int index)
		{
			int num = index * 3;
			Vector3 vector = this.GetPoint(num);
			Vector3 vector2;
			if (index > 0)
			{
				vector2 = this.GetPoint(num) - this.GetPoint(num - 1);
			}
			else
			{
				vector2 = this.GetPoint(num + 1) - this.GetPoint(num);
			}
			vector2 *= this.fixedVelocityOnNewNode;
			this.points.InsertRange(num + 1, new Vector3[3]);
			vector += vector2;
			this.points[num + 2] = vector;
			vector += vector2;
			this.points[num + 1] = vector;
			vector += vector2;
			this.points[num + 3] = vector;
			this.transformNodes.InsertRange(num + 1, new TransformNode[]
			{
				new TransformNode(),
				new TransformNode(),
				new TransformNode()
			});
			BezierControlPointMode value = this.modes[index];
			this.modes.Insert(index, BezierControlPointMode.Aligned);
			this.modes[index] = value;
			this.EnforceMode(index);
			this.SetControlPoint((index + 1) * 3, this.GetPoint((index + 1) * 3));
			if (this.loop)
			{
				this.points[this.points.Count - 1] = this.points[0];
				this.modes[this.modes.Count - 1] = this.modes[0];
				this.EnforceMode(0);
			}
		}

		// Token: 0x06000717 RID: 1815 RVA: 0x00029FC4 File Offset: 0x000281C4
		public virtual void RemoveFirst()
		{
			this.RemoveNode(0);
		}

		// Token: 0x06000718 RID: 1816 RVA: 0x00029FD0 File Offset: 0x000281D0
		public virtual void RemoveLast()
		{
			this.RemoveNode((this.points.Count - 1) / 3);
		}

		// Token: 0x06000719 RID: 1817 RVA: 0x00029FE8 File Offset: 0x000281E8
		public virtual void RemoveNode(int index)
		{
			index = Mathf.Clamp(index, 0, this.points.Count - 1);
			int num = index * 3;
			if (this.points.Count <= 4)
			{
				return;
			}
			if (num < this.points.Count - 1)
			{
				this.points.RemoveRange(num, 3);
				this.transformNodes.RemoveRange(num, 3);
			}
			else
			{
				this.points.RemoveRange(num - 2, 3);
				this.transformNodes.RemoveRange(num - 2, 3);
			}
			this.modes.RemoveAt(index);
			this.EnforceMode(index - 1);
			if (index > 0)
			{
				this.SetControlPoint((index - 1) * 3, this.GetPoint((index - 1) * 3));
			}
			else
			{
				this.SetControlPoint(0, this.GetPoint(0));
			}
		}

		// Token: 0x0600071A RID: 1818 RVA: 0x0002A0B8 File Offset: 0x000282B8
		public virtual void ReverseAllNodes()
		{
			this.points.Reverse();
			this.transformNodes.Reverse();
			this.modes.Reverse();
		}

		// Token: 0x0600071B RID: 1819 RVA: 0x0002A0DC File Offset: 0x000282DC
		public virtual void SwapNodes(int from, int to)
		{
			Vector3[] array = this.points.GetRange(from, 3).ToArray();
			Vector3[] array2 = this.points.GetRange(to, 3).ToArray();
			TransformNode[] array3 = this.transformNodes.GetRange(from, 3).ToArray();
			TransformNode[] array4 = this.transformNodes.GetRange(to, 3).ToArray();
			BezierControlPointMode value = this.modes[from];
			BezierControlPointMode value2 = this.modes[to];
			for (int i = from; i < 3; i++)
			{
				this.points[i] = array2[i];
				this.transformNodes[i] = array4[i];
			}
			for (int j = to; j < 3; j++)
			{
				this.points[j] = array[j];
				this.transformNodes[j] = array3[j];
			}
			this.modes[from] = value2;
			this.modes[to] = value;
		}

		// Token: 0x0600071C RID: 1820 RVA: 0x0002A1F0 File Offset: 0x000283F0
		public virtual Transform[] ExportToTransforms()
		{
			Transform[] array = new Transform[this.points.Count];
			for (int i = 0; i < this.points.Count; i++)
			{
				int num = (i + 1) / 3;
				int num2 = (i >= 3) ? (i % 3 % 2) : 0;
				bool flag = i == 0 || i % 3 == 0;
				array[i] = new GameObject((!flag) ? string.Concat(new object[]
				{
					"Node ",
					num,
					" - Bezier ",
					num2
				}) : ("Node " + num)).transform;
				array[i].parent = this.splineTransform;
				array[i].position = this.splineTransform.TransformPoint(this.GetInversePoint(i) + this.positionOffset);
			}
			if (this.exportWithNodeStructure)
			{
				for (int j = 2; j < array.Length; j++)
				{
					int num3 = (j >= 3) ? (j % 3 % 2) : 0;
					if (j != 0 && j % 3 != 0)
					{
						array[j].parent = array[(num3 != 0) ? (j - 1) : (j + 1)];
					}
				}
				array[1].parent = array[0];
			}
			return array;
		}

		// Token: 0x0600071D RID: 1821 RVA: 0x0002A35C File Offset: 0x0002855C
		public virtual Vector3[] ExportToVector3()
		{
			Vector3[] array = new Vector3[this.points.Count];
			for (int i = 0; i < this.points.Count; i++)
			{
				array[i] = this.GetPoint(i) + this.positionOffset;
			}
			return array;
		}

		// Token: 0x0600071E RID: 1822 RVA: 0x0002A3B8 File Offset: 0x000285B8
		public virtual void Reset()
		{
			this.points = new List<Vector3>
			{
				new Vector3(1f, 0f, 0f),
				new Vector3(2f, 0f, 0f),
				new Vector3(3f, 0f, 0f),
				new Vector3(4f, 0f, 0f)
			};
			this.modes = new List<BezierControlPointMode>
			{
				BezierControlPointMode.Aligned,
				BezierControlPointMode.Aligned
			};
			this.transformNodes = new List<TransformNode>
			{
				new TransformNode(),
				new TransformNode(),
				new TransformNode(),
				new TransformNode()
			};
		}

		// Token: 0x0600071F RID: 1823 RVA: 0x0002A490 File Offset: 0x00028690
		public virtual void OnEnable()
		{
			this.isReady = false;
			this.splineTransform = base.transform;
			this.SetMatrix();
		}

		// Token: 0x06000720 RID: 1824 RVA: 0x0002A4AC File Offset: 0x000286AC
		public virtual void Update()
		{
			this.SetMatrix();
			for (int i = 0; i < this.transformNodes.Count; i++)
			{
				this.transformNodes[i].Update(this.splineTransform);
			}
		}

		// Token: 0x06000721 RID: 1825 RVA: 0x0002A4F4 File Offset: 0x000286F4
		public virtual void SetMatrix()
		{
			if (this.previousPosition != this.splineTransform.position || this.previousRotation != this.splineTransform.rotation || this.previousScale != this.splineTransform.localScale)
			{
				this.splineTransformMx.SetTRS(this.splineTransform.position, this.splineTransform.rotation, this.splineTransform.localScale);
			}
			this.previousPosition = this.splineTransform.position;
			this.previousRotation = this.splineTransform.rotation;
			this.previousScale = this.splineTransform.localScale;
			this.isReady = true;
		}

		// Token: 0x04000710 RID: 1808
		[SerializeField]
		protected List<Vector3> points = new List<Vector3>();

		// Token: 0x04000711 RID: 1809
		[SerializeField]
		protected List<BezierControlPointMode> modes = new List<BezierControlPointMode>();

		// Token: 0x04000712 RID: 1810
		[SerializeField]
		protected bool loop;

		// Token: 0x04000713 RID: 1811
		[HideInInspector]
		public List<TransformNode> transformNodes = new List<TransformNode>();

		// Token: 0x04000714 RID: 1812
		[HideInInspector]
		public bool reverse;

		// Token: 0x04000715 RID: 1813
		[HideInInspector]
		public float timeOffset;

		// Token: 0x04000716 RID: 1814
		[HideInInspector]
		public Vector3 positionOffset;

		// Token: 0x04000717 RID: 1815
		[HideInInspector]
		public Transform splineTransform;

		// Token: 0x04000718 RID: 1816
		[HideInInspector]
		public Matrix4x4 splineTransformMx;

		// Token: 0x04000719 RID: 1817
		[HideInInspector]
		public List<Transform> usedBy = new List<Transform>();

		// Token: 0x0400071A RID: 1818
		[HideInInspector]
		public float fixedVelocityOnNewNode = 0.5f;

		// Token: 0x0400071B RID: 1819
		[HideInInspector]
		public bool moveTransformsAsBeziers;

		// Token: 0x0400071C RID: 1820
		[HideInInspector]
		public bool exportWithNodeStructure;

		// Token: 0x0400071D RID: 1821
		public static bool drawSplinePreviews = true;

		// Token: 0x0400071E RID: 1822
		[HideInInspector]
		public bool drawGizmo = true;

		// Token: 0x0400071F RID: 1823
		[HideInInspector]
		public float bezierWidth = 2f;

		// Token: 0x04000720 RID: 1824
		protected Vector3 previousPosition;

		// Token: 0x04000721 RID: 1825
		protected Quaternion previousRotation;

		// Token: 0x04000722 RID: 1826
		protected Vector3 previousScale;

		// Token: 0x04000723 RID: 1827
		protected bool isReady;
	}
}
